from os import name, write
from Functions import *
import time
import sys
import threading

continuous = False
rate = 10
myevent = threading.Event()

def initialize_camera(camera, name):
    global rate
    # 打开相机
    # open camera
    nRet = openCamera(camera)
    if ( nRet != 0 ):
        print("openCamera fail.")
        return None
        
    # 创建流对象
    # create stream source object
    streamSourceInfo = GENICAM_StreamSourceInfo()
    streamSourceInfo.channelId = 0
    streamSourceInfo.pCamera = pointer(camera)
      
    streamSource = pointer(GENICAM_StreamSource())
    nRet = GENICAM_createStreamSource(pointer(streamSourceInfo), byref(streamSource))
    if ( nRet != 0 ):
        print("create StreamSource fail!")
        return None
    
    # 通用属性设置:设置触发模式为off --根据属性类型，直接构造属性节点。如触发模式是 enumNode，构造enumNode节点
    # create corresponding property node according to the value type of property, here is enumNode
    # 自由拉流：TriggerMode 需为 off
    # set trigger mode to Off for continuously grabbing
    trigModeEnumNode = pointer(GENICAM_EnumNode())
    trigModeEnumNodeInfo = GENICAM_EnumNodeInfo() 
    trigModeEnumNodeInfo.pCamera = pointer(camera)
    trigModeEnumNodeInfo.attrName = b"TriggerMode"
    nRet = GENICAM_createEnumNode(byref(trigModeEnumNodeInfo), byref(trigModeEnumNode))
    if ( nRet != 0 ):
        print("create TriggerMode Node fail!")
        # 释放相关资源
        # release node resource before return
        streamSource.contents.release(streamSource) 
        return None
    
    nRet = trigModeEnumNode.contents.setValueBySymbol(trigModeEnumNode, b"Off")
    if ( nRet != 0 ):
        print("set TriggerMode value [Off] fail!")
        # 释放相关资源
        # release node resource before return
        trigModeEnumNode.contents.release(trigModeEnumNode)
        streamSource.contents.release(streamSource) 
        return None
      
    # 需要释放Node资源
    # release node resource at the end of use  
    trigModeEnumNode.contents.release(trigModeEnumNode) 
          
    # 注册拉流回调函数
    # subscribe grabbing callback
    userInfo = name.encode('utf-8')
    nRet = streamSource.contents.attachGrabbingEx(streamSource, frameCallbackFuncEx, userInfo)    
    if ( nRet != 0 ):
        print("attachGrabbingEx fail!")
        # 释放相关资源
        # release stream source object before return
        streamSource.contents.release(streamSource)  
        return None
          
    # 设置曝光
    # set ExposureTime
    nRet = setExposureTime(camera, int(1000000 / rate))
    if ( nRet != 0 ):
        print("set ExposureTime fail")
        # 释放相关资源
        # release stream source object before return
        streamSource.contents.release(streamSource)   
        return None
    
    return streamSource, userInfo

def start_camera(streamSource, camera, userInfo, fix):
    # 开始拉流
    # start grabbing
    nRet = streamSource.contents.startGrabbing(streamSource, c_ulonglong(0), \
                                               c_int(GENICAM_EGrabStrategy.grabStrartegySequential))
    if( nRet != 0):
        print("startGrabbing fail!")
        # 释放相关资源
        # release stream source object before return
        streamSource.contents.release(streamSource)   
        return -1
      
    # 自由拉流
    # grabbing
    if fix:
        time.sleep(1)
    else:
        while continuous:
            time.sleep(0.03)
  
    # 反注册回调函数
    # unsubscribe grabbing callback
    nRet = streamSource.contents.detachGrabbingEx(streamSource, frameCallbackFuncEx, userInfo) 
    if ( nRet != 0 ):
        print("detachGrabbingEx fail!")
        # 释放相关资源
        # release stream source object before return
        streamSource.contents.release(streamSource)  
        return -1

    # 停止拉流
    # stop grabbing
    nRet = streamSource.contents.stopGrabbing(streamSource)
    if ( nRet != 0 ):
        print("stopGrabbing fail!")
        # 释放相关资源
        # release stream source object before return
        streamSource.contents.release(streamSource)  
        return -1
    
    # 关闭相机
    # close camera
    nRet = closeCamera(camera)
    if ( nRet != 0 ):
        print("closeCamera fail")
        # 释放相关资源
        # release stream source object before return
        streamSource.contents.release(streamSource)   
        return -1
     
    # 释放相关资源
    # release stream source object at the end of use
    streamSource.contents.release(streamSource)    
    
    return 0

class synchro_camera(threading.Thread):
    def __init__(self, streamSource, camera, userInfo, fix):
        threading.Thread.__init__(self)
        self.streamSource = streamSource
        self.camera = camera
        self.userInfo = userInfo
        self.fix = fix

    def run(self):
        global myevent
        if myevent.is_set():
            myevent.wait()
            start_camera(self.streamSource, self.camera, self.userInfo, self.fix)
            WriteFrames(self.userInfo)
            myevent.clear()
        else:
            myevent.set()

def demo(fix=True):
    global frameBuff_dict, convertParams_dict, continuous

    # 发现相机
    # enumerate camera
    cameraCnt, cameraList = enumCameras()
    if cameraCnt is None:
        return -1
    
    # 显示相机信息
    # print camera info
    for index in range(0, cameraCnt):
        camera = cameraList[index]
        print("\nCamera Id = " + str(index))
        print("Key           = " + str(camera.getKey(camera)))
        print("vendor name   = " + str(camera.getVendorName(camera)))
        print("Model  name   = " + str(camera.getModelName(camera)))
        print("Serial number = " + str(camera.getSerialNumber(camera)))
        
    camera_0 = cameraList[0]
    streamSource_0, userInfo_0 = initialize_camera(camera_0, '0')
    if streamSource_0 is None:
        return -1
    camera_1 = cameraList[1]
    streamSource_1, userInfo_1 = initialize_camera(camera_1, '1')
    if streamSource_1 is None:
        return -1

    myevent.set()
    for streamSource, camera, userInfo in zip([streamSource_0, streamSource_1], [camera_0, camera_1], [userInfo_0, userInfo_1]):
        t = synchro_camera(streamSource, camera, userInfo, fix)
        t.start()

    return 0
    
if __name__=="__main__": 

    nRet = demo()
    if nRet != 0:
        print("Some Error happend")
    print("--------- Demo end ---------")